package com.tsing.common.filter;

import com.tsing.common.config.ShiroConfigProp;
import com.tsing.common.exceptions.BusinessException;
import com.tsing.common.exceptions.CommonException;
import com.tsing.common.service.BaseRedisService;
import com.tsing.common.service.UserRedisService;
import com.tsing.common.utils.FilterMapUtil;
import com.tsing.common.vo.UserVo;
import org.apache.shiro.util.Assert;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Map;

public class FrameShiroFilter extends AccessControlFilter {

    @Autowired
    private UserRedisService userRedisService;

    @Autowired
    ShiroConfigProp shiroConfigProp;

    @Value("${frame.shiro.support:false}")
    String frameSupport;

    @Autowired
    private BaseRedisService baseRedisService;

    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        return false;
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        if (!"true".equals(frameSupport)) {
            return true;
        }
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        String servletPath = httpServletRequest.getServletPath();
        // 先判断是否是系统配置的不需要校验的访问，例如登录请求，或者其他静态资源
        Map<String, String> filterChainDefinition = shiroConfigProp.getfilterChainDefinitionMap();
        // 在这里做判断
        if (FilterMapUtil.wildcardMatchMapKey(filterChainDefinition, servletPath, "anon")) {
            return true;
        }
        // 从http请求头中取出
        String token = httpServletRequest.getHeader("token");
        Assert.notNull(token, "token不能为空");
        UserVo userVo = userRedisService.getUserByToken(token);
        if (userVo == null) {
            throw new BusinessException(CommonException.Proxy.TOKEN_USER_NOT_EXIST);
        }
        if (userVo.isMini()) {
            return true;
        }
        try {
            ArrayList<String> allUri = new ArrayList<>();
            for (String role : userVo.getRoleIds()) {
                allUri.addAll(userRedisService.getPermission(role));
            }
            if (allUri.size() < 1) {
                throw new BusinessException(CommonException.Proxy.SHIRO_URI_EXCEPTIONT);
            } else {
                for (String uri : allUri) {
                    if (servletPath.equals(uri)) {
                        return true;
                    }
                }
                throw new BusinessException(CommonException.Proxy.SHIRO_AUTHORIZATION_EXCEPTIONT);
            }
        } catch (Exception e) {
            throw new BusinessException(CommonException.Proxy.SHIRO_AUTHORIZATION_EXCEPTIONT);
        }
    }

}
